#include <assert.h>
#include <string.h>
#ifdef __linux__
#include <sys/ipc.h>
#include <sys/shm.h>
#endif

#include "vipc_shm.h"
#include "vmalloc.h"

struct shm__
{
    int shmid;
    int shmsize;
};

vShm vShmCreate(const char *name,int size)
{
    struct shm__ *ctx = (struct shm__*)vCalloc(1,sizeof(struct shm__));
    assert(ctx);

    key_t key = ftok(name,1);
    ctx->shmsize = size > 0 ? size : 1024;
    ctx->shmid = shmget(key,ctx->shmsize,IPC_CREAT | IPC_EXCL | 0666);
    if(ctx->shmid < 0)
    {
        vFree(ctx);
        return NULL;
    }

    return (vShm)ctx;
}

void vShmDelete(vShm vs)
{
    vFree(vs);
}

int vShmWrite(vShm vs,void *buf,size_t len)
{
    struct shm__ *ctx = (struct shm__*)vs;
    assert(ctx);

    void *shm = shmat(ctx->shmid,0,0);
    if(shm == (void *)-1)
        return -1;

    memcpy(shm,buf,(len > ctx->shmsize ? ctx->shmsize : len));
    shmdt(shm);
    return 0;
}

int vShmRead(vShm vs,void *buf,size_t len)
{
    struct shm__ *ctx = (struct shm__*)vs;
    assert(ctx);
    void *shm = shmat(ctx->shmid,0,0);
    if(shm == (void *)-1)
        return -1;
    memcpy(buf,shm,(len > ctx->shmsize ? ctx->shmsize : len));
    shmdt(shm);
    return 0;
}
